//
// Created by martin on 2/16/22.
//

#ifndef MUDUO_TCPCONNECTION_H
#define MUDUO_TCPCONNECTION_H

#include "muduo/base/noncopyable.h"
#include "muduo/net/Callbacks.h"
#include "muduo/net/InetAddress.h"
#include "muduo/net/Buffer.h"

#include <memory>
#include <string>
#include <boost/any.hpp>

//#include <netinet/tcp.h>
struct tcp_info;

namespace muduo
{
namespace net
{

class Channel;
class EventLoop;
class Socket;

/**
 * Tcp连接, 为服务器和客户端使用.
 * 接口类, 因此不要暴露太多细节.
 */
class TcpConnection : noncopyable,
	public std::enable_shared_from_this<TcpConnection> // std::shared_ptr<TcpConnection> getSelf()
{
public:
	/*
	 * 用已连接sockfd构造一个TcpConnection对象.
	 * 用户不应该自行创建该对象. 通常由TcpServer或TcpClient来创建该对象
	 */
	TcpConnection(EventLoop* loop,
		const std::string& nameArg,
		int sockfd,
		const InetAddress& localAddr,
		const InetAddress& peerAddr);
	~TcpConnection();
	/* 获取所属EventLoop */
	EventLoop* getLoop() const { return loop_; }
	/* 获取对象名称, 便于调试, 跟踪 */
	const std::string& name() const { return name_; }
	/* 返回本地IP地址 */
	const InetAddress& localAddress() const { return localAddr_; }
	/* 返回对端IP地址 */
	const InetAddress& peerAddress() const { return peerAddr_; }
	/* 查询状态是否为已连接 */
	bool connected() const { return state_ == kConnected; }
	/* 查询状态是否为已断开连接 */
	bool disconnected() const { return state_ == kDisconnected; }
	// return true if success.
	bool getTcpInfo(struct tcp_info*) const;
	std::string getTcpInfoString() const;

	/* 发送消息给连接对端 */
//    void send(std::string&& mesage); // C++11
	void send(const void* message, int len);
	void send(const StringPiece& message);
	void send(Buffer&& message);
	void send(Buffer* message); // this one will swap data

	/* 关闭写半连接 */
	void shutdown(); // NOT thread safe, no simultaneous calling
//    void shutdownAndForceCloseAfter(double seconds); // NOT thread safe, no simultaneous calling

	/* 强制关闭连接 */
	void forceClose();
	/* 强制延时关闭连接 */
	void forceCloseWithDelay(double seconds);
	/* 设置TCP_NODELAY选项, 禁用Nagle算法 */
	void setTcpNoDelay(bool on);
	// reading or not
	/* 使能监听读事件 */
	void startRead();
	/* 禁用监听读事件 */
	void stopRead();
	/* 判断是否正在监听读事件 */
	bool isReading() const { return reading_; }

	void setContext(const boost::any& context)
	{
		context_ = context;
	}

	const boost::any& getContext() const
	{
		return context_;
	}

	boost::any* getMutableContext()
	{
		return &context_;
	}

	void setConnectionCallback(const ConnectionCallback& cb)
	{
		connectionCallback_ = cb;
	}

	void setMessageCallback(const MessageCallback& cb)
	{
		messageCallback_ = cb;
	}

	void setWriteCompleteCallback(const WriteCompleteCallback& cb)
	{
		writeCompleteCallback_ = cb;
	}

	void setHighWaterMarkCallback(const HighWaterMarkCallback& cb, size_t highWaterMark)
	{
		highWaterMarkCallback_ = cb; highWaterMark_ = highWaterMark;
	}

	/* Advanced interface */

	Buffer* inputBuffer()
	{
		return &inputBuffer_;
	}

	Buffer* outputBuffer()
	{
		return &outputBuffer_;
	}

	/* Internal use only */
	void setCloseCallback(const CloseCallback& cb)
	{
		closeCallback_ = cb;
	}

	// called when TcpServer accepts a new connection
	void connectEstablished(); // should be called only once per connection
	// called when TcpServer has removed me from its map
	void connectDestroyed(); // should be called only once per connection

private:
	enum StateE { kDisconnected, kConnecting, kConnected, kDisconnecting }; // TCP连接状态定义
	void handleRead(Timestamp receiveTime); // 处理读事件
	void handleWrite();                     // 处理写事件
	void handleClose();                     // 处理关闭连接事件
	void handleError();                     // 处理错误事件
	/* loop线程中排队发送消息 */
	void sendInLoop(std::string&& message); // C++11 // add by martin
	void sendInLoop(const StringPiece& message);
	void sendInLoop(const char* message, size_t len);
	/* loop线程中排队关闭写连接 */
	void shutDownInLoop();
	void shutDownAndForceCloseInLoop(double seconds); // add by martin
	/* loop线程中排队关闭连接 */
	void forceCloseInLoop();
	/*　设置TcpConnection状态 */
	void setState(StateE s) { state_ = s; }
	/* 将状态转换为字符串 */
	const char* stateToString() const;
	/* loop线程中排队开始监听读事件 */
	void startReadInLoop();
	/* loop线程中排队关闭监听读事件 */
	void stopReadInLoop();

	EventLoop* loop_;     // 所属　EventLoop
	std::string name_;    // 名称
	StateE state_; // FIXME: use atomic varaible　//　状态
	bool reading_; // whether the connection is reading // 连接是否正在监听读事件
	// we don't expose those classes to client.
	std::unique_ptr<Socket> socket_;              // 连接套接字, 用于对连接进行底层操作
	std::unique_ptr<Channel> channel_;            // 通道, 用于绑定要监听的事件
	InetAddress localAddr_;                       // 本地IP地址
	InetAddress peerAddr_;                        // 对端IP地址
	ConnectionCallback connectionCallback_;       // 连接回调
	MessageCallback messageCallback_;             // 收到消息回调
	WriteCompleteCallback writeCompleteCallback_; // 写完成回调
	HighWaterMarkCallback highWaterMarkCallback_; // 高水位回调
	CloseCallback closeCallback_;                 // 关闭连接回调
	size_t highWaterMark_;                        // 高水位阈值
	Buffer inputBuffer_;                          // 输入缓冲区
	Buffer outputBuffer_; // FIXME: use list<Buffer> as output buffer.　//　输出缓冲区
	boost::any context_;                           // 用户自定义参数, 如果context_为智能指针(shared_ptr/unique_ptr), TcpConnection析构时, 自动释放接管的资源
	// FIXME: createTime_, lastReceiveTime_
	//        bytesReceived_, bytesSent_
};

typedef std::shared_ptr<TcpConnection> TcpConnectionPtr;
typedef std::weak_ptr<TcpConnection>   TcpConnectionWeakPtr;

} // namespace net
} // namespace muduo

#endif //MUDUO_TCPCONNECTION_H
